package com.cly.config;

import com.cly.properties.ThreadPoolProperties;
import com.cly.result.exception.ServiceException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 异步配置
 * <p>
 * 用于配置高并发异步请求
 *
 * @author 春风能解释
 * <p>
 * 2023/3/16
 */
@Configuration
@EnableAsync // 启用异步任务
@Slf4j
@RequiredArgsConstructor
public class ThreadConfig implements AsyncConfigurer {

    /**
     * 线程池配置
     */
    private final ThreadPoolProperties threadPoolProperties;

    /**
     * 初始化异步线程
     *
     * @return 线程池
     */
    @Bean(name = "customThreadPoolTaskExecutor")
    public ThreadPoolTaskExecutor executor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 配置核心线程数
        executor.setCorePoolSize(threadPoolProperties.getCorePoolSize());
        // 配置最大线程数
        executor.setMaxPoolSize(threadPoolProperties.getMaxPoolSize());
        // 配置队列大小
        executor.setQueueCapacity(threadPoolProperties.getQueueCapacity());
        // 线程的名称前缀
        executor.setThreadNamePrefix(threadPoolProperties.getNamePrefix());
        // 线程活跃时间（秒）
        executor.setKeepAliveSeconds(threadPoolProperties.getKeepAliveSeconds());
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        // 设置拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        // 执行初始化
        executor.initialize();
        log.info("线程池配置完成!");
        return executor;
    }

    /**
     * 配置线程池
     *
     * @return 线程池
     */
    @Override
    public Executor getAsyncExecutor() {
        return executor();
    }

    /**
     * 异常捕获
     *
     * @return 异步异常捕获器
     */
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return ((ex, method, params) -> {
            log.warn("方法{}在线程中发生异常!异常信息:{}", method.getName(), ex.getLocalizedMessage());
            throw new ServiceException(ex);
        });
    }
}
